#include "pca9557.h"
/**
 * @brief 读取PCA9557寄存器的值
 * 
 * @param reg_addr 
 * @param data 
 * @param len 
 * @return esp_err_t 
 */
esp_err_t pca9557_register_read(uint8_t reg_addr, uint8_t *data, uint32_t len)
{
    return i2c_master_write_read_device(I2C_NUM, PCA9557_SENSOR_ADDR, &reg_addr, 1, data, len, 1000 / portTICK_PERIOD_MS );
}

/**
 * @brief 给PCA9557的寄存器写值
 * 
 * @param reg_addr 
 * @param data 
 * @return esp_err_t 
 */
esp_err_t pca9557_register_write_byte(uint8_t reg_addr, uint8_t data)
{
    uint8_t data_buf[2] = {reg_addr, data};
    return i2c_master_write_to_device(I2C_NUM, PCA9557_SENSOR_ADDR, data_buf, sizeof(data_buf), 1000 / portTICK_PERIOD_MS);
}

/**
 * @brief I2C_init
 * @note I2C初始化函数
 * @return esp_err_t 
 */
esp_err_t I2C_init(void)
{
    i2c_config_t i2c_conf  = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = I2C_SDA,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_io_num = I2C_SCL,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = I2C_FREQ_HZ
    };
    i2c_param_config(I2C_NUM, &i2c_conf);

    return i2c_driver_install(I2C_NUM, i2c_conf.mode, 0, 0, 0);
}

/**
 * @brief 初始化PCA9557 IO扩展芯片
 * @param NULL
 */
void pca9557_init(void)
{
    //写入控制引脚默认值 DVP_PWDN =1 PA_EN = 0 LCD_CS = 1
    pca9557_register_write_byte(PCA9577_OUTPUT_PORT, 0x05);
    //把PCA9557芯片的IO0 IO1 IO2 设置为输出 其它引脚保持默认的输入
    pca9557_register_write_byte(PCA9557_CONFIGURATION_PORT, 0xf8);
}

/**
 * @brief 设置PCA9557芯片的某个IO引脚输出高低电平
 * 
 * @param gpio_bit 
 * @param level 高低电平
 * @return esp_err_t 
 */
esp_err_t pca9557_set_output_state(uint8_t gpio_bit, uint8_t level)
{
    uint8_t data;
    esp_err_t res = ESP_FAIL;
    pca9557_register_read(PCA9577_OUTPUT_PORT, &data, 1);
    res = pca9557_register_write_byte(PCA9577_OUTPUT_PORT, SET_BITS(data, gpio_bit, level));

    return res;
}

/**
 * @brief 控制PCA8557_LCD_CS引脚输出高低电平
 * 
 * @param level 0：输出低电平 1：输出高电平
 */
void lcd_cs(uint8_t level)
{
    pca9557_set_output_state(LCD_CS_GPIO, level);
}



/**
 * @brief 控制PCA8557_PA_EN引脚输出高低电平
 * 
 * @param level 0：输出低电平 1：输出高电平
 */
void pa_en(uint8_t level)
{
    pca9557_set_output_state(PA_EN_GPIO, level);
}

/**
 * @brief 控制PCA8557_DVP_PWDN引脚输出高低电平
 * 
 * @param level 0：输出低电平 1：输出高电平
 */
void dvp_pwdn(uint8_t level)
{
    pca9557_set_output_state(DVP_PWDN_GPIO, level);
}
